package cn.vconinfo.database.interceptor;

import cn.vconinfo.database.annotation.MybatisFixedParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Statement;
import java.util.Properties;

/**
 * mybatis拦截器
 * @author vconinfo
 * @creaetdOn 18:37 2020/8/31
 * @description:
 */
@Slf4j
@Component
@Configuration
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args={Statement.class, ResultHandler.class})})
public class MybatisInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        //id为执行的mapper方法的全路径名，如com.**.UserMapper.insertUser
        String id = mappedStatement.getId();
        log.debug("拦截mapper方法-->{}", id);
        // sql语句类型 select、delete、insert、update
        String sqlCommandType = mappedStatement.getSqlCommandType().toString();
        BoundSql boundSql = statementHandler.getBoundSql();
        //获取到原始sql语句
        String sql = boundSql.getSql();
        String mSql = sql;

        Object parameter = statementHandler.getParameterHandler().getParameterObject();
//        int saasId = 0;
//        if (parameter instanceof ListQuery && ((ListQuery) parameter).getSAAS_ID()!= null) {
//            saasId = ((ListQuery) parameter).getSAAS_ID();
//        }
//        if (parameter instanceof BaseModel && ((BaseModel) parameter).getSAAS_ID()!=null) {
//            saasId = ((BaseModel) parameter).getSAAS_ID();
//        }

        Class<?> classType = Class.forName(mappedStatement.getId().substring(0, mappedStatement.getId().lastIndexOf(".")));
        String mName = mappedStatement.getId().substring(mappedStatement.getId().lastIndexOf(".") + 1, mappedStatement.getId().length());
        for (Method method : classType.getDeclaredMethods()) {
            if (method.isAnnotationPresent(MybatisFixedParam.class) && mName.equals(method.getName())) {
                log.debug("拦截mapper：请求类型={}，sql={}，", sqlCommandType, sql);
                log.debug("参数：{}", parameter);
                MybatisFixedParam mybatisFixedParam = method.getAnnotation(MybatisFixedParam.class);
//                if (mybatisFixedParam.mark()) {
//                    if (mSql.contains("SAAS_ID")) {
//                        mSql = mSql.replaceAll("\\$\\{SAAS_ID\\}", saasId + "");
//                    }
//                }
            }
        }
        Field field = boundSql.getClass().getDeclaredField("sql");
        field.setAccessible(true);
        field.set(boundSql, mSql);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, new MybatisInterceptor());
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
